<script lang="tsx">
import { defineComponent, ref, watch, computed, nextTick, onBeforeUnmount } from 'vue';
import { $t } from '@vben/locales';

export default defineComponent({
  name: 'MenuPermissionTree',
  props: {
    // 树形数据
    data: {
      type: Array,
      default: () => []
    },
    // 当前选中的节点keys
    modelValue: {
      type: Array,
      default: () => []
    },
    // 树形组件的props配置
    treeProps: {
      type: Object,
      default: () => ({ label: 'name', children: 'children' })
    },
    // 节点的唯一标识
    nodeKey: {
      type: String,
      default: 'id'
    },
    // 是否显示复选框
    showCheckbox: {
      type: Boolean,
      default: true
    },
    // 是否默认展开所有节点
    defaultExpandAll: {
      type: Boolean,
      default: true
    },
    // 是否点击节点展开
    expandOnClickNode: {
      type: Boolean,
      default: true
    },
    // 全选按钮文本
    selectAllText: {
      type: String,
      default: () => $t('system.role.selectAll')
    },
    // 展开全部文本
    expandAllText: {
      type: String,
      default: () => $t('system.role.expandAll')
    },
    // 收起全部文本
    collapseAllText: {
      type: String,
      default: () => $t('system.role.collapseAll')
    },
    // 是否显示操作栏
    showHeader: {
      type: Boolean,
      default: true
    },
    // el-tree 透传属性
    treeAttrs: {
      type: Object,
      default: () => ({})
    },
    // el-checkbox 透传属性
    checkboxAttrs: {
      type: Object,
      default: () => ({})
    }
  },
  emits: ['update:modelValue', 'check', 'allCheck', 'expandCollapse'],
  setup(props, { emit }) {
    const treeRef = ref();
    const isExpanded = ref(props.defaultExpandAll);

    // 全选状态
    const allChecked = computed(() => {
      return props.modelValue.length === getAllNodeIds(props.data).length;
    });

    // 半选状态
    const indeterminate = computed(() => {
      if (!props.data.length) return false;
      const allIds = getAllNodeIds(props.data);
      const checkedCount = props.modelValue.length;
      return checkedCount > 0 && checkedCount < allIds.length;
    });

    // 获取所有节点的 id
    const getAllNodeIds = (nodes: any[]): any[] => {
      const ids: any[] = [];
      const traverse = (nodeList: any[]) => {
        nodeList.forEach(node => {
          ids.push(node[props.nodeKey]);
          if (node[props.treeProps.children] && node[props.treeProps.children].length > 0) {
            traverse(node[props.treeProps.children]);
          }
        });
      };
      traverse(nodes);
      return ids;
    };

    // 获取所有叶子节点的 id
    const getAllLeafNodeIds = (nodes: any[]): any[] => {
      const leafIds: any[] = [];
      const traverse = (nodeList: any[]) => {
        nodeList.forEach(node => {
          if (!node[props.treeProps.children] || node[props.treeProps.children].length === 0) {
            // 叶子节点
            leafIds.push(node[props.nodeKey]);
          } else {
            // 父节点，继续遍历子节点
            traverse(node[props.treeProps.children]);
          }
        });
      };
      traverse(nodes);
      return leafIds;
    };

    // 从选中的节点中过滤出叶子节点
    const getLeafNodesFromSelected = (selectedIds: any[]): any[] => {
      if (!props.data.length || !selectedIds.length) return [];
      
      const allLeafIds = getAllLeafNodeIds(props.data);
      return selectedIds.filter(id => allLeafIds.includes(id));
    };

    // 设置选中状态的方法
    const setCheckedState = () => {
      if (!Array.isArray(props.modelValue) || !props.data.length) return;
      
      nextTick(() => {
        if (!treeRef.value) return;
        
        // 先清空所有选中状态
        treeRef.value.setCheckedKeys([]);
        
        // 只设置叶子节点为选中，让父节点的半选状态自动计算
        const leafNodes = getLeafNodesFromSelected(props.modelValue);
        treeRef.value.setCheckedKeys(leafNodes);
      });
    };

    // 监听选中值变化，同步到树组件
    watch(() => props.modelValue, setCheckedState, { immediate: true });
    
    // 监听数据变化，当数据加载后重新设置选中状态
    watch(() => props.data, () => {
      if (props.data.length > 0) {
        setCheckedState();
      }
    }, { deep: true });
    // 全选/取消全选
    const handleAllCheck = () => {
      if (!treeRef.value) return;
      let newCheckedKeys: any[] = [];
      if (!allChecked.value) {
        // 全选
        newCheckedKeys = getAllNodeIds(props.data);
        treeRef.value.setCheckedKeys(newCheckedKeys);
      } else {
        // 取消全选
        treeRef.value.setCheckedKeys([]);
      }
      emit('update:modelValue', newCheckedKeys);
      emit('allCheck', newCheckedKeys, !allChecked.value);
    };

    // 监听树选择变化
    const handleTreeCheck = (data: any, checked: any) => {
      if (!treeRef.value) return;
      
      // 获取完全选中的节点
      const checkedKeys = treeRef.value.getCheckedKeys(false) || [];
      // 获取半选状态的节点（父节点）
      const halfCheckedKeys = treeRef.value.getHalfCheckedKeys() || [];
      
      // 合并完全选中和半选状态的节点
      const allSelectedKeys = [...checkedKeys, ...halfCheckedKeys];
      
      // console.log('checkedKeys:', checkedKeys, 'halfCheckedKeys:', halfCheckedKeys, 'allSelectedKeys:', allSelectedKeys);
      emit('update:modelValue', allSelectedKeys);
      emit('check', data, checked, allSelectedKeys);
    };

    // 全部展开/收起
    const handleExpandCollapse = () => {
      if (!treeRef.value) return;
      isExpanded.value = !isExpanded.value;
      const allIds = getAllNodeIds(props.data);

      allIds.forEach(id => {
        const node = treeRef.value.getNode(id);
        if (node) {
          node.expanded = isExpanded.value;
        }
      });
      emit('expandCollapse', isExpanded.value);
    };

    // 组件销毁时清理
    onBeforeUnmount(() => {
      // 清理树引用
      treeRef.value = null;
    });

    return () => (
      <div class="w-full h-full menu-permission-tree border border-[#E5E5E5] rounded-lg">
        {props.showHeader && (
          <div class="flex justify-between items-center bg-[#F3F3F3] px-4 rounded-t-lg">
            <el-checkbox
              v-model={allChecked.value}
              indeterminate={indeterminate.value}
              label={props.selectAllText}
              size="large"
              onChange={handleAllCheck}
              {...props.checkboxAttrs}
            />
            <el-button
              type="primary"
              link
              onClick={handleExpandCollapse}
            >
              {isExpanded.value ? props.collapseAllText : props.expandAllText}
            </el-button>
          </div>
        )}

        <div class="w-full h-full rounded-b-lg p-4 flex-1 overflow-auto">
          <el-tree
            ref={treeRef}
            data={props.data}
            props={props.treeProps}
            node-key={props.nodeKey}
            show-checkbox={props.showCheckbox}
            expand-on-click-node={props.expandOnClickNode}
            default-expand-all={props.defaultExpandAll}
            onCheck={handleTreeCheck}
            {...props.treeAttrs}
          />
        </div>
      </div>
    );
  }
});
</script>

<style scoped>
.menu-permission-tree {
  display: flex;
  flex-direction: column;
}

.menu-permission-tree .flex-1 {
  flex: 1;
  min-height: 0;
}
</style>
